package org.mx.graphql.service.impl;

import org.mx.RandomUtils;
import org.mx.graphql.bean.EventInfo;
import org.mx.graphql.bean.EventSummary;
import org.mx.graphql.bean.EventSummaryInfo;
import org.mx.graphql.bean.Person;
import org.mx.graphql.service.EventQuery;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@SuppressWarnings("javadoc")
@Component("eventQuery")
public class EventQueryImpl implements EventQuery {
    private Map<String, EventInfo> events;
    private String[] categories = {"category 1", "category 2", "category 3", "category 4"};

    public EventQueryImpl() {
        super();
        createInitializedEvents();
    }

    private void createInitializedEvents() {
        events = new HashMap<>();
        Map<String, Person> persons = new HashMap<>();
        persons.put("1", new Person("1", "john", "13100183736"));
        persons.put("2", new Person("2", "tom", "13500183737"));
        persons.put("3", new Person("3", "mike", "13600183738"));
        persons.put("4", new Person("4", "linus", "13900183739"));
        events.put("1", new EventInfo(1, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("2", new EventInfo(2, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("3", new EventInfo(3, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("4", new EventInfo(4, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("5", new EventInfo(5, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("6", new EventInfo(6, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("7", new EventInfo(7, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("8", new EventInfo(8, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("9", new EventInfo(9, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("10", new EventInfo(10, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("11", new EventInfo(11, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("12", new EventInfo(12, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("13", new EventInfo(13, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
        events.put("14", new EventInfo(14, categories[RandomUtils.randomInt(0, 4)],
                persons.get("" + RandomUtils.randomInt(0, 3))));
    }

    @Override
    public EventInfo getEventById(String id) {
        return events.get(id);
    }

    @Override
    public EventSummaryInfo getEventSummary() {
        EventSummaryInfo eventSummaryInfo = new EventSummaryInfo();
        long total = 0L;
        long[] totalByCategory = new long[categories.length];
        for (EventInfo eventInfo : events.values()) {
            total += 1;
            String category = eventInfo.getCategory();
            for (int index = 0; index < categories.length; index ++) {
                if (categories[index].equalsIgnoreCase(category)) {
                    totalByCategory[index] += 1;
                }
            }
        }
        eventSummaryInfo.setTotal(total);
        List<EventSummary> byCategory = new ArrayList<>();
        for (int index = 0; index < totalByCategory.length; index ++) {
            byCategory.add(new EventSummary(categories[index], totalByCategory[index], (double)totalByCategory[index] * 100 / total));
        }
        eventSummaryInfo.setByCategory(byCategory);
        return eventSummaryInfo;
    }

    @Override
    public List<EventInfo> getSimilarEvents(String content) {
        return events.values().stream().filter(eventInfo -> {
            if (eventInfo == null) {
                return false;
            } else if (eventInfo.getAddress().contains(content)) {
                return true;
            } else if (eventInfo.getCategory().contains(content)) {
                return true;
            } else if (eventInfo.getContent().contains(content)) {
                return true;
            } else if (eventInfo.getName().contains(content)) {
                return true;
            } else if (eventInfo.getPerson() != null) {
                return eventInfo.getPerson().getName().contains(content);
            }
            return false;
        }).collect(Collectors.toList());
    }
}
